package com.imu.purse.mq.conumer;


import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.imu.constant.Constant;
import com.imu.enums.TransStatus;
import com.imu.purse.modules.app.entity.ImuUserEntity;
import com.imu.purse.modules.app.service.ImuUserService;
import com.imu.purse.modules.bitcoin.BitcoinApi;
import com.imu.purse.modules.bitcoin.form.BitcoinForm;
import com.imu.purse.modules.trade.entity.BitcoinLogEntity;
import com.imu.purse.modules.trade.service.BitcoinLogService;
import com.imu.purse.modules.trade.service.TradeInfoService;
import com.imu.purse.mq.bean.TransBean;
import com.imu.purse.mq.produce.BitcoinProduce;
import com.rabbitmq.client.Channel;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Component
public class BitcoinConsumer {
	private static final Log log = LogFactory.get(BitcoinConsumer.class);

	@Autowired
	private BitcoinProduce bitcoinProduce;

	@Autowired
	private BitcoinApi bitcoinApi;

	@Autowired
	private BitcoinLogService bitcoinLogService;

	@Autowired
	private TradeInfoService tradeInfoService;

	@Autowired
	private ImuUserService userService;

	@Autowired
	private RedisTemplate<String, String> redisTemplate;



	/* DIRECT模式.
    * @param message the message
    * @param channel the channel
    */
	@RabbitListener(queues = {"BIT_DIRECT_QUEUE"})
	public void message(Message message, Channel channel) {
		try{
			//解析消息
			parseData(message);
		}catch(Exception e){//抛出异常，则该条消息需要重新存入数据库中
			log.error(e);
			//重新推入队列
			sendToProduce(message);
		}finally {
			try{
				channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
			}catch (Exception e){
				//重新推入队列
				sendToProduce(message);
				log.error(e);
			}
		}
	}

	/**
	 * 如果有问题重新丢入队列中
	 * @param message
	 */
	private void sendToProduce(Message message){
		if(message != null && message.getBody() != null){
			String data = new String(message.getBody());
			if(StringUtils.isNotEmpty(data)){
				//将消息转换为对象
				TransBean bean = JSON.parseObject(data, TransBean.class);
				if(bean == null){
					return;
				}
				bitcoinProduce.sendData(bean);
			}
		}
	}

	/**
	 * 解析数据
	 * @param message
	 */
	private void parseData(Message message){
		if(message != null && message.getBody() != null){
			String data = new String(message.getBody());
			if(StringUtils.isNotEmpty(data)){
				//将消息转换为对象
				TransBean bean = JSON.parseObject(data, TransBean.class);
				if(bean == null){
					return;
				}
				boolean queueFlag = handleTransData(bean);
				if(queueFlag){
					saveTransRecord(bean);
					bean.setDataType(1);
					bitcoinProduce.sendData(bean);
				}else{//代表该交易已无效聊
					bitcoinLogService.deleteByTId(bean.getTransId());
				}
			}
		}

	}
	/**
	 * 处理交易的数据
	 * @param bean
	 * @return true 需要回写到队列，false：不需要
	 */
	private boolean handleTransData(TransBean bean){
		//CoreMoneyAddr moneyAddr = JSON.parseObject(bean.getCoreMoneyAddr(),CoreMoneyAddr.class);
		//根据交易id获取数据
		Map<String,Object> iMap = bitcoinApi.gettransaction(bean.getTransId(),bean.getCoreMoneyAddr());
		if(CollectionUtils.isEmpty(iMap)){
			return false;
		}
		long curTime = getCurrentSec();//获取当前时间的秒数
		if(iMap.get("error") != null &&
				Constant.MONEY_PACKAGE_CONNECT_OTHER_ERROR.equals(iMap.get("error").toString())){
			long transTime = Long.valueOf(redisTemplate.opsForValue().get(Constant.CORE_MONEY_TRANS_EXPIRE));

			if(curTime  - bean.getTransTime() > transTime * 60){//超过指定的时间，则抛弃掉该条记录
				return false;
			}
			return true;
		}
		if(iMap.get("error") != null && Constant.MONEY_PACKAGE_CONNECT_ERROR.equals(iMap.get("error").toString())){
			return true;
		}

		//确认次数
		Object confirmNum = iMap.get("confirmations");
		if(confirmNum == null || Integer.valueOf(confirmNum.toString()) < 6){
			return true;
		}
		//以下处理该批交易的数据 ,如果列表中只有1条记录，代表是外部转账，否则是内部转账,如果没有记录，则当前数据不需要再发送到队列中
		Object obj = iMap.get("details");
		if(obj == null){
			return false;
		}
		List<Object> iList = (List<Object>)obj;
		//处理相应的数据
		handleTransData(bean,iList,curTime);

		return false;
	}

	/**
	 * 处理数据
	 * @param bean
	 * @param iList
	 * @param curTime
	 */
	private void handleTransData(TransBean bean,List<Object> iList,long curTime){
		if(CollectionUtils.isEmpty(iList)){
			return;
		}
		List<BitcoinForm> fList = Lists.newArrayList();

		String cacheUser = null;
		//内部转入时，存在两条记录，但是由于核心钱包那边问题，可能只存在一条记录
		//外部转入时，存在一条记录，即catalog为recevie
		//当记录为1条时，存在两种情况，catalog：send，代表是内部转账(目前测试是该种情况)


		for(Object obj : iList){
			if(obj != null){
				Map<String,Object> oMap = (Map<String,Object>)obj;
				//通过该账号获取用户信息
				cacheUser = redisTemplate.opsForValue().get(oMap.get("account"));
				ImuUserEntity user = null;
				if(cacheUser == null){//说明该账号不是我们这边交易的记录,如果缓存不存在，则从数据去取
					user = userService.queryByMobile(oMap.get("account").toString());
					if(user == null){
						continue;
					}
					redisTemplate.opsForValue().set(oMap.get("account").toString(),
							JSON.toJSONString(user));
				}else{
					user = JSON.parseObject(cacheUser,ImuUserEntity.class);
				}
				
				BitcoinForm sForm = new BitcoinForm();
				sForm.setAccount(oMap.get("account").toString());
				sForm.setAddress(oMap.get("address").toString());//内部转账的时候通过手机转账，地址都是对方
				sForm.setCategory(oMap.get("category").toString());
				sForm.setAmount(new BigDecimal(oMap.get("amount").toString()));
				sForm.setLabel(oMap.get("label") == null ? null : oMap.get("label").toString());
				sForm.setVout(Integer.valueOf(oMap.get("vout").toString()));
				sForm.setFee(oMap.get("fee") == null ? new BigDecimal(0) : new BigDecimal(oMap.get("fee").toString()));
				sForm.setTransId(bean.getTransId());
				sForm.setTransTime(bean.getTransTime());

				sForm.setUserId(user.getId());
				sForm.setCurTime(curTime);
				sForm.setOrderState(TransStatus.FINISH.getType());
				fList.add(sForm);
				sForm = null;
			}
		}
		if(!fList.isEmpty()){
			//修改交易信息
			tradeInfoService.modBitData(fList);
		}
		fList = null;

	}

	/**
	 * 获取当前时间秒数
	 * @return
	 */
	private long getCurrentSec(){
		String curStr = System.currentTimeMillis() + "";
		return Long.valueOf(curStr.substring(0, curStr.length()-3));
	}

	/**
	 * 记录交易信息
	 * @param bean
	 */
	private void saveTransRecord(TransBean bean){
		if(bean.getDataType() == 0){//新记录，则也需要插入数据库
			BitcoinLogEntity entity = new BitcoinLogEntity();
			BeanUtils.copyProperties(bean, entity);
			bitcoinLogService.save(entity);
		}
	}
}
